package com.sixkey.exception;

import com.sixkey.response.Response;
import com.sixkey.response.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.ResponseUtil;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

/**
 * ClassName: ExceptionHandler
 * Package: com.sixkey.exception
 * Description:
 *
 * @Author: @weixueshi
 * @Create: 2023/9/27 - 17:32
 * @Version: v1.0
 */

/**
 * 获取全局异常
 */
@Slf4j
@RestControllerAdvice
public class IExceptionHandler {

    /**
     * 获取业务异常
     */
    @ExceptionHandler(ServiceException.class)
    public Response serviceException(HttpServletRequest request,ServiceException e){
        printLog(request,e);
        log.error("报业务异常：{}",e.getMessage());
        return Response.error(e.getCode() , e.getMessage());
    }

    /**
     * 捕获参数校验异常
     */
    @ExceptionHandler(BindException.class)
    public Response sqlException(HttpServletRequest request,BindException e){
        printLog(request,e);
        log.error("报参数校验异常：{}",e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        return Response.error(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    /**
     * 捕获SQL异常
     */
    @ExceptionHandler(SQLException.class)
    public Response sqlException(HttpServletRequest request,SQLException e){
        printLog(request,e);
        log.error("报SQL异常：{}",e.getMessage());
        return Response.error(e.getMessage());
    }

    /**
     * 打印日志信息
     * @param request
     * @param exception
     */
    private static void printLog(HttpServletRequest request, Exception exception) {
        //换行符
        String lineSeparatorStr = System.getProperty("line.separator");

        StringBuilder exStr = new StringBuilder();
        StackTraceElement[] trace = exception.getStackTrace();
        // 获取堆栈信息并输出为打印的形式
        for (StackTraceElement s : trace) {
            exStr.append("\tat " + s + "\r\n");
        }
        //打印error级别的堆栈日志
        log.error("访问地址：" + request.getRequestURL() + ",请求方法：" + request.getMethod() +
                ",远程地址：" + request.getRemoteAddr() + lineSeparatorStr +
                "错误堆栈信息如下:" + exception.toString() + lineSeparatorStr + exStr);
    }
}
